﻿using System;
using System.ComponentModel.Composition;
using OperationPlugins.Compositions;

namespace OperationPlugins.WebApp.Applications
{
    internal static class ApplicationServer
    {
        private static IApplicationServerDataContext DataContext { get; set; }

        /// <summary>
        /// The application server status.
        /// </summary>
        internal static ApplicationServerStatus Status { get; private set; }

        /// <summary>
        /// Checks if the application server can be started right now.
        /// </summary>
        internal static bool CanBeStarted
        {
            get { return Status == ApplicationServerStatus.Initialized || Status == ApplicationServerStatus.Stopped; }
        }

        /// <summary>
        /// Checks if the application server can be stopped right now.
        /// </summary>
        internal static bool CanBeStopped
        {
            get { return Status == ApplicationServerStatus.Starting || Status == ApplicationServerStatus.Running; }
        }

        /// <summary>
        /// Checks if the application server can be recycled right now.
        /// </summary>
        internal static bool CanBeRecycled
        {
            get { return Status == ApplicationServerStatus.Running; }
        }

        /// <summary>
        /// Starts the application server.
        /// </summary>
        internal static void Start()
        {
            SetStatus(ApplicationServerStatus.Starting);
        }

        /// <summary>
        /// Stops the application server.
        /// </summary>
        internal static void Stop()
        {
            SetStatus(ApplicationServerStatus.Stopping);
        }

        /// <summary>
        /// Recycles the application server.
        /// </summary>
        internal static void Recycle()
        {
        }


        private static void SetStatus(ApplicationServerStatus newStatus)
        {
            Status = newStatus;

            switch (newStatus)
            {
                case ApplicationServerStatus.Initializing:
                    break;

                case ApplicationServerStatus.Initialized:
                    bool autoStart = false;
                    try
                    {
                        autoStart = DataContext.IsRunning;
                    }
                    catch (Exception ex)
                    {
                        // TODO: Log exception
                    }
                    if (autoStart)
                    {
                        SetStatus(ApplicationServerStatus.Starting);
                    }
                    break;
                
                case ApplicationServerStatus.Stopping:
                    SetStatus(ApplicationServerStatus.Stopped);
                    break;
                
                case ApplicationServerStatus.Stopped:
                    DataContext.IsRunning = false;
                    break;
                
                case ApplicationServerStatus.Starting:
                    SetStatus(ApplicationServerStatus.Running);
                    break;
                
                case ApplicationServerStatus.Running:
                    DataContext.IsRunning = true;
                    break;
                
                default:
                    throw new ArgumentOutOfRangeException("newStatus");
            }
        }


        /// <summary>
        /// Initialize. 
        /// </summary>
        [Export(typeof(IInitialize))]
        private sealed class Initializer : IInitialize
        {
            void IInitialize.Initialize(InitializationContext context)
            {
                DataContext = context.CompositionContainer.GetPlugin<IApplicationServerDataContext>();
                SetStatus(ApplicationServerStatus.Initializing);
            }
        }

        /// <summary>
        /// Initialized. 
        /// </summary>
        [Export(typeof(IInitialized))]
        private sealed class Initialized : IInitialized
        {
            void IInitialized.Initialized(InitializationContext context)
            {
                SetStatus(ApplicationServerStatus.Initialized);
            }

        }

    }
}